﻿namespace ScrumLite.WebUx.Tests
{
    using System;
    using System.Collections.Generic;
    using System.Collections.ObjectModel;
    using ScrumLite.Services;
    using ScrumLite.Services.Contracts;
    using System.Linq;
    using System.Globalization;

    public class MockRequestsService : IRequestsService
    {
        public bool SetPrioritiesCalled { get; set; }
        public bool AddRequestCalled { get; set; }
        public bool UpdateRequestCalled { get; set; }
        public bool DeleteRequestCalled { get; set; }
        public bool GetWorkAreasCalled { get; set; }
        public bool GetWeeklyWeightCalled { get; set; }
        public bool GetWorkAreasGroupByWeightCalled { get; set; }
        public bool GetRequestsByStatusByWorkAreaCalled { get; set; }
        public bool GetRequestsByStatusCalled { get; set; }
        public bool CleanCommittedCalled { get; set; }
        public Request ProcessedRequest { get; set; }
        public const string ProjectIdForEmptyData = "13c659fb-fa13-4343-ba36-1af8b48eee97";

        public Dictionary<int, int> WeeklyWeightToReturn { get; private set; }
        public static List<string> ProjectToReturn { get; set; }
        public static Dictionary<string, List<WorkArea>> WorkAreasToReturn { get; set; }
                    
        public MockRequestsService()
        {
            ProjectToReturn = new List<string>(new string[] {
                        "Project1",
                        "Project2",
                        "Project3",
                        "Project4",
                        "AF06A611-12CE-4C06-B3AD-E2754D12D516"
                    });

            List<WorkArea> workAreas = new List<WorkArea>();
            workAreas.Add(new WorkArea { Id = "BB184E41-B84D-4c2f-9251-CB0F8E8D7DDB", Name = "Site Admin Tool" });
            workAreas.Add(new WorkArea { Id = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB", Name = "Modularity" });
            WorkAreasToReturn = new Dictionary<string, List<WorkArea>>();
            WorkAreasToReturn.Add(ProjectToReturn[4], workAreas );

            WeeklyWeightToReturn = new Dictionary<int, int>();
            WeeklyWeightToReturn.Add(1, 20);
            WeeklyWeightToReturn.Add(2, 24);
            WeeklyWeightToReturn.Add(3, 50);
            WeeklyWeightToReturn.Add(4, 45);
            WeeklyWeightToReturn.Add(5, 55);
            WeeklyWeightToReturn.Add(6, 93);
        }

        public Request[] GetCommittedRequests(string projectId)
        {
            List<Request> requests = new List<Request>();
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 1, Notes = "Notes for the request", Priority = 1, Status = RequestStatus.Waiting, Title = "Request 1" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 2, Notes = "Notes for the request", Priority = 2, Status = RequestStatus.Completed, Title = "Completed Request 2" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 3, Notes = null, Priority = 3, Status = RequestStatus.Taken, Title = "Taken Request 3" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 4, Notes = "* Note 1 Note 1 Note 1 Note 1 Note 1 Note 1\r\n* Note 2 Note 2 Note 2 Note 2 Note 2 Note 2", Priority = 4, Status = RequestStatus.Postponed, Title = "Postponed Request 4" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 5, Notes = null, Priority = 5, Status = RequestStatus.Blocked, Title = "Blocked Request 5" });

            return requests.ToArray();
        }

        public Collection<Request> GetRequests(string projectId, string workArea)
        {
            string workAreaName = "newArea";

            List<Request> requests = new List<Request>();
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 1, Notes = "Notes for the request", Priority = 1, Status = RequestStatus.Waiting, Title = "Request 1" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 2, Notes = "Notes for the request", Priority = 2, Status = RequestStatus.Completed, Title = "Completed Request 2" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 3, Notes = null, Priority = 3, Status = RequestStatus.Taken, Title = "Taken Request 3" });
            if (workArea != workAreaName)
            {
                requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 4, Notes = "* Note 1 Note 1 Note 1 Note 1 Note 1 Note 1\r\n* Note 2 Note 2 Note 2 Note 2 Note 2 Note 2", Priority = 4, Status = RequestStatus.Postponed, Title = "Postponed Request 4" });
                requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 5, Notes = null, Priority = 5, Status = RequestStatus.Blocked, Title = "Blocked Request 5" });
                requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 6, Notes = null, Priority = 5, Status = RequestStatus.Blocked, Title = "Blocked Request 5" });
            }
            return new Collection<Request>(requests);
        }

        public void SetPriorities(Guid[] requestIds)
        {
            SetPrioritiesCalled = true;
        }

        public int AddRequest(string projectId, Request request)
        {
            AddRequestCalled = true;
            ProcessedRequest = request;
            return request.Moniker;
        }

        public void UpdateRequest(string projectId, Request request)
        {
            UpdateRequestCalled = true;
            ProcessedRequest = request;
        }

        public Dictionary<string, string> GetStatusList()
        {
            Dictionary<string, string> status = new Dictionary<string, string>();
            status.Add(((byte)RequestStatus.Blocked).ToString(CultureInfo.InvariantCulture), Enum.GetName(typeof(RequestStatus), RequestStatus.Blocked));
            status.Add(((byte)RequestStatus.Completed).ToString(CultureInfo.InvariantCulture), Enum.GetName(typeof(RequestStatus), RequestStatus.Completed));
            status.Add(((byte)RequestStatus.Postponed).ToString(CultureInfo.InvariantCulture), Enum.GetName(typeof(RequestStatus), RequestStatus.Postponed));
            status.Add(((byte)RequestStatus.Taken).ToString(CultureInfo.InvariantCulture), Enum.GetName(typeof(RequestStatus), RequestStatus.Taken));
            status.Add(((byte)RequestStatus.Waiting).ToString(CultureInfo.InvariantCulture), Enum.GetName(typeof(RequestStatus), RequestStatus.Waiting));

            return status;
        }

        public Request GetRequest(string projectId, int moniker)
        {
            return new Request() { Priority = 2, Title = "Test to update", Notes = "Test to update", Moniker = 1, Requestor = "tester", Status = RequestStatus.Taken, Committed = false, Order = 1 };
        }

        public static int GetNextMoniker(string projectId)
        {
            throw new NotImplementedException(projectId);
        }

        public void SaveRequests(string projectId, Request[] requests)
        {
            throw new NotImplementedException(projectId);
        }

        public Request[] GetOpenedRequests(string projectId)
        {
            List<Request> requests = new List<Request>();
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 1, Notes = "Notes for the request", Priority = 1, Status = RequestStatus.Waiting, Title = "Request 1" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 2, Notes = "Notes for the request", Priority = 2, Status = RequestStatus.Completed, Title = "Completed Request 2" });
            requests.Add(new Request() { Id = Guid.NewGuid(), Moniker = 3, Notes = null, Priority = 3, Status = RequestStatus.Taken, Title = "Taken Request 3" });

            return requests.ToArray();
        }

        public void DeleteRequest(Guid requestId)
        {
            DeleteRequestCalled = true;
        }
        public WorkArea[] GetWorkAreas(string projectId)
        {
            GetWorkAreasCalled = true;

            List<WorkArea> areas = new List<WorkArea>();

            if (WorkAreasToReturn.ContainsKey(projectId))
            {
                areas = WorkAreasToReturn[projectId];
            }

            return areas.ToArray();
        }

        public WorkArea[] GetWorkAreasByMoniker(string projectId, int moniker)
        {
            GetWorkAreasCalled = true;

            List<WorkArea> areas = new List<WorkArea>();
            areas.Add(new WorkArea {Id = "AA184E41-B84D-4c2f-9251-CB0F8E8D7DDB", Name = "Fake WorkArea"});

            return areas.ToArray();
        }

        public WorkAreaWeight[] GetWorkAreasGroupByWeight(string projectId)
        {
            GetWorkAreasGroupByWeightCalled = true;
            List<WorkAreaWeight> data = new List<WorkAreaWeight>();

            if (projectId != ProjectIdForEmptyData)
            {
                WorkAreaWeight wa = new WorkAreaWeight();
                wa.Name = "Site Admin Tool";
                wa.Weight = 23;
                wa.Deliverables = 3;
                wa.Requests = 8;

                data.Add(wa);
                data.Add(new WorkAreaWeight() { Name = "Modularity", Weight = 65, Requests = 12 });
                data.Add(new WorkAreaWeight() { Name = "Management", Weight = 34, Requests = 32 });
            }
            return data.ToArray();
        }

        public void AssignWorkAreas(string projectId, int moniker, string[] workAreaIds)
        {
            throw new NotImplementedException(projectId);
        }

        public WorkArea GetWorkArea(string projectId, Guid id)
        {            
            return WorkAreasToReturn[projectId].First(algo => (new Guid(algo.Id)) == id);
        }

        public void SaveWorkArea(WorkArea wa, Guid projectId)
        {
            return;
        }

        public Dictionary<int, int> GetWeeklyWeight(string projectId)
        {
            GetWeeklyWeightCalled = true;

            if (projectId != ProjectIdForEmptyData)
            {
                return WeeklyWeightToReturn;
            }
            else
            {
                return new Dictionary<int, int>();
            }
        }

        public Dictionary<WorkArea, Dictionary<RequestStatus, int>> GetRequestsByStatusByWorkArea(string projectId)
        {
            GetRequestsByStatusByWorkAreaCalled = true;
            Dictionary<WorkArea, Dictionary<RequestStatus, int>> result = new Dictionary<WorkArea, Dictionary<RequestStatus, int>>();

            if (WorkAreasToReturn.ContainsKey(projectId))
            {
                foreach (WorkArea workArea in WorkAreasToReturn[projectId])
                {
                    Dictionary<RequestStatus, int> requestsByStatus = new Dictionary<RequestStatus, int>();
                    requestsByStatus.Add(RequestStatus.Blocked, 1);
                    requestsByStatus.Add(RequestStatus.Completed, 4);
                    requestsByStatus.Add(RequestStatus.Postponed, 0);
                    requestsByStatus.Add(RequestStatus.Taken, 3);
                    requestsByStatus.Add(RequestStatus.Waiting, 2);
                    result.Add(workArea, requestsByStatus);
                }
            }
            return result;
        }

        public Dictionary<RequestStatus, int> GetRequestsByStatus(string projectId)
        {
            GetRequestsByStatusCalled = true;
            Dictionary<WorkArea, Dictionary<RequestStatus, int>> byStatusByWorkArea = GetRequestsByStatusByWorkArea(projectId);
            Dictionary<RequestStatus, int> byStatus = new Dictionary<RequestStatus, int>();

            foreach (WorkArea workArea in byStatusByWorkArea.Keys)
            {
                foreach (RequestStatus status in byStatusByWorkArea[workArea].Keys)
                {
                    if (!byStatus.ContainsKey(status))
                    {
                        byStatus[status] = byStatusByWorkArea[workArea][status];
                    }
                    else
                    {
                        byStatus[status] += byStatusByWorkArea[workArea][status];
                    }
                }
            }
            return byStatus;
        }

        public void CleanCommitted(string projectId, RequestStatus[] statusToUpdateCommitted)
        {
            CleanCommittedCalled = true;
        }

        public int GetRequestsTotalWeight(string projectId)
        {
            throw new NotImplementedException();
        }

        public Dictionary<DayOfWeek, int> GetCommittedDailyWeight(string projectId)
        {
            throw new NotImplementedException();
        }

        public int GetCommittedRequestsTotalWeight(string projectId)
        {
            throw new NotImplementedException();
        }
    }
}
